package com.ht.api.task.ad;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import com.ht.api.business.ad.PlanHelper;
import com.ht.api.db.Db;
import com.ht.api.db.DbConfig;
import com.ht.api.db.DbList;
import com.ht.api.db.Entity;
import com.ht.api.db.StreamLoadConfig;
import com.ht.api.db.task.HtTaskExecutor;
import com.ht.api.db.task.TaskHandler;
import com.ht.api.open.OpenUtil;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 检查群发消息客服发布状态
 */
@Slf4j
public class CheckMsgUserStatusTask implements TaskHandler  {

    /** 接口ID：获取群发成员发送任务列表*/
    protected static final long API_ID = 1903071666200776704L;

    /** 接口ID：获取企业群发成员执行结果 */
    protected static final long RESULT_API_ID = 1903072886390919168L;

	@Override
	public String getName() {
		return "检查群发消息客服发布状态";
	}

    @Override
    public boolean handler(JSONObject requestParam, String groupId, long taskId) {
        long tenantId = requestParam.getLong("tenant_id");
        DataSource ds = DbConfig.useTenantDb(tenantId);
        StreamLoadConfig config = DbConfig.useTenantSLC(tenantId);

        String adTaskGroupId = requestParam.getStr("ad_task_group_id");
        Entity adTaskGroup = Db.createSqlParser("ad_task_group").where("main_id", adTaskGroupId).findOne(ds);

        String msgid = requestParam.getStr("msgid");
        String appid = requestParam.getStr("appid");

        JSONObject param = JSONUtil.createObj();
        param.set("msgid", msgid);

        String str = OpenUtil.call(appid, API_ID, param);
        JSONObject result = JSONUtil.parseObj(str);

        List<Entity> dataList = new ArrayList<>();

        String creativeId = adTaskGroup.getStr("creative_id");
        Entity creative = Db.createSqlParser("creative").where("main_id", creativeId).findOne(ds);

        JSONArray materials = creative.getJSONArray("material");

        Map<String, List<Entity>> linkRelationMap = new HashMap<>();
        if (materials != null) {
            for (int i = 0; i < materials.size(); i++) {
                JSONObject material = materials.getJSONObject(i);
                String type = material.getStr("type");

                if (type.equals("link")) {
                    String linkId = material.getStr("link_id");
                    Entity link = Db.createSqlParser("short_link").where("main_id", linkId).findOne(ds);

                    String relationId = link.getStr("relation_id");
                    String relationTable = link.getStr("relation_type");

                    Entity linkRelation = Entity.create(relationTable);
                    linkRelation.set("main_id", relationId);
                    linkRelation.set("exposure_count", 0);

                    if (!linkRelationMap.containsKey(relationTable)) {
                        linkRelationMap.put(relationTable, new ArrayList<>());
                    }

                    linkRelationMap.get(relationTable).add(linkRelation);
                }
            }
        }

        boolean isLink = false;
        List<Runnable> taskRunList = new ArrayList<>();


        boolean isFinish = true;
        JSONArray taskList = result.getJSONArray("task_list");
        for (int i = 0; i < taskList.size(); i++) {
            JSONObject task = taskList.getJSONObject(i);
            String userid = task.getStr("userid");
            int publishStatus = task.getInt("status");

            if (publishStatus == 2) {
                adTaskGroup.set("status", 4);

                Entity msgUser = Entity.create("wx_msg_user");
                msgUser.set("ad_task_group_id", adTaskGroupId);
                msgUser.set("userid", userid);
                msgUser.set("publish_status", publishStatus);
                msgUser.set("publish_time", task.get("send_time"));
                dataList.add(msgUser);

                JSONObject resultparam = JSONUtil.createObj();
                resultparam.set("msgid", msgid);
                resultparam.set("userid", userid);
                resultparam.set("limit", 1000);

                String resultstr = OpenUtil.call(appid, RESULT_API_ID, resultparam);
                JSONObject resultObj = JSONUtil.parseObj(resultstr);

                DbList adtaskList = Db.createSqlParser("ad_user_task").where("ad_task_group_id", adTaskGroupId).query(ds);
                Map<String, Entity> adtaskMap = new HashMap<>();
                for (Entity adtask : adtaskList) {
                    adtaskMap.put(adtask.getStr("touch_id") + adtask.getStr("openid"), adtask);
                }
                JSONArray sendList = resultObj.getJSONArray("send_list");
                for (int k = 0; k < sendList.size(); k++) {
                    JSONObject customer = sendList.getJSONObject(k);

                    Entity msgCustomer = Entity.create("wx_msg_customer");
                    msgCustomer.set("ad_task_group_id", adTaskGroupId);
                    msgCustomer.set("userid", userid);
                    msgCustomer.set("openid", customer.get("external_userid"));
                    msgCustomer.set("status", customer.get("status")); //如果这里存在不是好友关系，则正好维护客服与客户的关系状态
                    msgCustomer.set("send_time", customer.get("send_time"));

                    dataList.add(msgCustomer);

                    Entity adtask = adtaskMap.get(userid + customer.get("external_userid"));
                    int status = customer.getInt("status");

                    if (status == 1) {
                        adtask.set("status", 3);
                        adtask.set("act_time", customer.get("send_time"));
                    } else if (status == 2){
                        adtask.set("status", 5);
                        adtask.set("act_time", DateUtil.now());
                        adtask.set("result_msg", "因客户不是好友导致发送失败");
                    } else if (status == 3){
                        adtask.set("status", 5);
                        adtask.set("act_time", DateUtil.now());
                        adtask.set("result_msg", "因客户已经收到其他群发消息导致发送失败");
                    }

                    if (adtask != null) {
                        dataList.add(adtask);
                    }

                    if (linkRelationMap.size() > 0) {
                        for (String relation : linkRelationMap.keySet()) {
                            List<Entity> linkRelationList = linkRelationMap.get(relation);
                            for (Entity entity : linkRelationList) {
                                entity.set("exposure_count", entity.getInt("exposure_count") + 1);
                            }

                            switch (relation) {
                                case "writings":
                                    taskRunList.add(()->{
                                        String oneid = Db.createSqlParser("user_origin")
                                                .select("oneid").where("openid", task.get("openid")).val(ds, String.class);
                                        Entity entity = Entity.create("content_preference");
                                        entity.set("main_id", oneid);
                                        entity.set("oneid", oneid);
                                        entity.set("show_count", linkRelationList.size());
                                        dataList.add(entity);
                                    });

                                    break;
                            }
                        }
                    }
                }

                HtTaskExecutor.stopTask(taskId);
            } else {
                isFinish = false;
            }
        }

        if (isFinish) {
            adTaskGroup.set("status", 5);
            HtTaskExecutor.stopTask(taskId);
        }

        if (isLink) {
            for (String relation : linkRelationMap.keySet()) {
                dataList.addAll(linkRelationMap.get(relation));
            }
        }

        HtTaskExecutor.execute(taskRunList);

        dataList.add(adTaskGroup);

        Db.insertBatchWithStream(config, dataList);

        String planId = adTaskGroup.getStr("plan_id");
        if (StrUtil.isNotBlank(planId)) {
            PlanHelper.checkPlanStatus(ds, config, planId);
        }

        return true;
    }
}
